package com.citycloud.ccuap.tc.admin.projectrole;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.citycloud.ccuap.commons.json.CheckedTreeNode;
import com.citycloud.ccuap.commons.sys.entity.SysAct;
import com.citycloud.ccuap.commons.sys.entity.SysDeptment;
import com.citycloud.ccuap.commons.sys.entity.SysGroup;
import com.citycloud.ccuap.commons.sys.entity.SysProject;
import com.citycloud.ccuap.commons.sys.entity.SysRole;
import com.citycloud.ccuap.commons.sys.entity.SysUser;
import com.citycloud.ccuap.commons.sys.repository.SysActRepository;
import com.citycloud.ccuap.commons.sys.repository.SysDeptmentRepository;
import com.citycloud.ccuap.commons.sys.repository.SysGroupRepository;
import com.citycloud.ccuap.commons.sys.repository.SysProjectRepository;
import com.citycloud.ccuap.commons.sys.repository.SysRoleRepository;
import com.citycloud.ccuap.commons.sys.repository.SysUserRepository;
import com.citycloud.ccuap.commons.sys.role.RoleMapper;
import com.citycloud.ccuap.framework.exception.ApplicationException;
import com.citycloud.ccuap.framework.service.mybatis.MybatisServiceImpl;
import com.citycloud.ccuap.framework.util.ExcelUtil;
import com.citycloud.ccuap.tc.admin.entity.SysAuthLog;
import com.citycloud.ccuap.tc.admin.entity.SysProjectAcl;
import com.citycloud.ccuap.tc.admin.entity.SysProjectDgRoleRel;
import com.citycloud.ccuap.tc.admin.entity.SysProjectFunction;
import com.citycloud.ccuap.tc.admin.repository.SysAuthLogRepository;
import com.citycloud.ccuap.tc.admin.repository.SysProjectAclRepository;
import com.citycloud.ccuap.tc.admin.repository.SysProjectDgRoleRelRepository;
import com.citycloud.ccuap.tc.admin.repository.SysProjectFunctionRepository;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 角色信息业务处理实现
 *
 * @author sufeng
 */

@Service
@Slf4j
public class ProjectRoleService extends MybatisServiceImpl<SysRoleRepository, SysRole, Long> implements IProjectRoleService {
    @Autowired
    private SysProjectDgRoleRelRepository sysProjectDgRoleRelRepository;

    @Autowired
    private SysProjectFunctionRepository sysProjectFunctionRepository;

    @Autowired
    private SysProjectAclRepository sysProjectAclRepository;

    @Autowired
    private SysUserRepository sysUserRepository;

    @Autowired
    private SysProjectRepository sysProjectRepository;

    @Autowired
    private SysGroupRepository sysGroupRepository;

    @Autowired
    private SysDeptmentRepository sysDeptmentRepository;

    @Autowired
    private SysAuthLogRepository sysAuthLogRepository;

    @Autowired
    private SysActRepository sysActRepository;


    @Resource
    @Lazy
    private RoleMapper roleMapper;
    
    @Autowired
    private SysRoleRepository sysRoleRepository;

    @Override
    public void updateLinkedDatagroup(Long roleId, List<String> datagroups) {
        sysProjectDgRoleRelRepository.deleteByRoleId(roleId);
        for (String datagroup : datagroups) {
            SysProjectDgRoleRel sysProjectDgRoleRel = new SysProjectDgRoleRel();
            sysProjectDgRoleRel.setRoleId(roleId);
            sysProjectDgRoleRel.setDatagroupId(datagroup);
            sysProjectDgRoleRelRepository.save(sysProjectDgRoleRel);
        }
    }


    @Override
    public List<CheckedTreeNode> findAllProjectFunNodeTree(Long roleId, Long projectId) {
        List<CheckedTreeNode> treeList = new ArrayList<>();
        List<SysProjectFunction> nodeList;
        nodeList = sysProjectFunctionRepository.findByProjectIdOrderByOrderNo(projectId);
        List<SysProjectAcl> aclList = sysProjectAclRepository.findByRoleId(roleId);
        List<String> funIdList = new ArrayList<>();
        for (SysProjectAcl acl : aclList) {
            funIdList.add(acl.getPrjFunId());
        }

        for (SysProjectFunction sysProjectFunction : nodeList) {
            if (sysProjectFunction.getPid() == null) {
                CheckedTreeNode node = new CheckedTreeNode();
                String funId = sysProjectFunction.getFunId();
                node.setId(sysProjectFunction.getPrjFunId());
                node.setText(sysProjectFunction.getFunName());
                node.setNavigation(sysProjectFunction.getFunId());
                node.setExpanded(true);
                boolean isLeaf = !hasChildNode(funId, sysProjectFunction.getProjectId());
                node.setLeaf(isLeaf);
                if (isLeaf) {
                    node.setChecked(funIdList.contains(sysProjectFunction.getPrjFunId()));
                }
                treeList.add(findChildren(node, nodeList, funIdList));
            }
        }
        return treeList;
    }

    /**
     * 递归查找子节点
     *
     * @param treeNode
     * @param funList
     * @return
     */
    private CheckedTreeNode findChildren(CheckedTreeNode treeNode, List<SysProjectFunction> funList, List<String> funIdList) {
        for (SysProjectFunction sysFunction : funList) {
            if (sysFunction.getPid() != null && treeNode.getNavigation().equals(sysFunction.getPid())) {
                if (treeNode.getChildren() == null) {
                    treeNode.setChildren(new ArrayList<CheckedTreeNode>());
                }
                CheckedTreeNode node = new CheckedTreeNode();
                String funId = sysFunction.getFunId();
                node.setId(sysFunction.getPrjFunId());
                node.setText(sysFunction.getFunName());
                node.setNavigation(sysFunction.getFunId());
                node.setExpanded(true);
                boolean isLeaf = !hasChildNode(funId, sysFunction.getProjectId());
                node.setLeaf(isLeaf);
                if (isLeaf) {
                    node.setChecked(funIdList.contains(sysFunction.getPrjFunId()));
                }

                treeNode.getChildren().add(findChildren(node, funList, funIdList));
            }
        }
        return treeNode;
    }

    /**
     * 父节点下是否存在子节点
     *
     * @param pid 父节点
     * @return
     */
    private boolean hasChildNode(String pid, Long projectId) {
        Long count = sysProjectFunctionRepository.countByPidAndProjectId(pid, projectId);

        if (count == 0) {
            return false;
        } else {
            return true;
        }
    }


    @Override
    public void grantFunction(Long roleId, List<String> funIdList) {
        sysProjectAclRepository.deleteByRoleId(roleId);
        for (String funId : funIdList) {
            SysProjectAcl sysAcl = new SysProjectAcl();
            sysAcl.setRoleId(roleId);
            sysAcl.setPrjFunId(funId);
            sysProjectAclRepository.save(sysAcl);
        }
    }


    @Override
    public Map<String, List<String>> grantRoleToUsers(Long roleId, List<Long> userIds, List<Long> deptIds, Long projectId, String data, String ip, List<Long> addUserIds, List<Long> delUserIds) {
        SysRole sysRole = repository.findById(roleId).orElse(null);
        Assert.notNull(sysRole, "查询角色信息为空");
        //判断该角色之前绑定的用户是否存在此次修改中，不存在则进行处理
        List<Map<String, Object>> currentList = selectList(" SELECT user_id FROM sys_act where role_id= " + roleId, true);
        for (Map<String, Object> map : currentList) {
            Long curUserId = Long.valueOf(map.get("userId").toString());
            if (!userIds.contains(curUserId)) {
                SysUser sysUser = sysUserRepository.findById(curUserId).orElse(null);
                Assert.notNull(sysUser, "查询用户信息为空");
                //查询该用户拥有的角色名称（排除当前角色）
                List<Map<String, Object>> roleNameList = selectList(" SELECT role.role_name FROM sys_role role inner join sys_act act on role.role_id=act.role_id where act.user_id = " + curUserId + " and act.role_id <> " + roleId, true);
                StringBuilder nameBuilder = new StringBuilder();
                for (Map<String, Object> nameMap : roleNameList) {
                    nameBuilder.append(nameMap.get("roleName").toString()).append(",");
                }
                String roleNames = nameBuilder.toString();
                sysUser.setOwnRoles(roleNames.length() == 0 ? "" : roleNames.substring(0, roleNames.length() - 1));
                sysUserRepository.update(sysUser);
            }
        }

        sysActRepository.deleteByRoleId(roleId);
        if (userIds.size() != deptIds.size()) {
            throw new ApplicationException(400, "传入参数异常！");
        }

        StringBuilder userBuilder = new StringBuilder();
        for (int i = 0; i < userIds.size(); i++) {
            Long userId = userIds.get(i);
            Long deptId = deptIds.get(i);
            SysUser sysUser = sysUserRepository.findById(userId).orElse(null);
            Assert.notNull(sysUser, "查询用户信息为空");
            userBuilder.append(sysUser.getUserName()).append(",");

            SysAct sysAct = new SysAct();
            sysAct.setRoleId(roleId);
            sysAct.setUserId(userId);
            sysAct.setDeptId(deptId);
            sysActRepository.save(sysAct);
            // 查找用户所有角色
            List<Map<String, Object>> roleNameList = roleMapper.findRoleNameByUserId(userId);
            StringBuilder roleBuilder = new StringBuilder();
            for (Map<String, Object> map : roleNameList) {
                roleBuilder.append(map.get("role_name")).append(",");
            }
            String roleNames = roleBuilder.toString();
            sysUser.setOwnRoles(roleNames.length() == 0 ? "" : roleNames.substring(0, roleNames.length() - 1));
            sysUserRepository.save(sysUser);
        }
        String userNames = userBuilder.toString();
        sysRole.setGrantUsers(userNames.length() == 0 ? "" : userNames.substring(0, userNames.length() - 1));
        repository.save(sysRole);
        List<String> adduserNameList = saveAuthlog(projectId, data, ip, addUserIds, sysRole, true);
        List<String> deluserNameList = saveAuthlog(projectId, data, ip, delUserIds, sysRole, false);
        Map<String, List<String>> map = Maps.newHashMap();
        map.put("adduser", adduserNameList);
        map.put("deluser", deluserNameList);
        return map;
    }


    @Override
    public Map<String, List<String>> grantUsers(RoleUserDTO roleUserDTO, String data, String ip, Long projectId) {
        SysRole sysRole = repository.findById(roleUserDTO.getRoleId()).orElse(null);
        Assert.notNull(sysRole, "查询角色信息为空");
        //判断该角色之前绑定的用户是否存在此次修改中，不存在则进行处理
        List<SysAct> actList = sysActRepository.findByRoleId(roleUserDTO.getRoleId());
        //原来该角色分配的userId集合
        List<Long> actUserIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(actList)) {
            for (SysAct act : actList) {
                actUserIds.add(act.getUserId());
            }
        }
        //当前请求过来的userId集合
        List<Long> newUserIds = new ArrayList<>();
        for (UserDeptDTO userDeptDTO : roleUserDTO.getUserDepts()) {
            newUserIds.add(userDeptDTO.getUserId());
        }

        //差集 原来的-当前传入的集合,取出已被移除的用户id
        List<Long> hasRemovedUserIds = actUserIds.stream().filter(num -> !newUserIds.contains(num))
                .collect(Collectors.toList());

        //差集，当前传入的集合-原来的集合,取出新增的用户id集合
        List<Long> addUserIds = newUserIds.stream().filter(num -> !actUserIds.contains(num))
                .collect(Collectors.toList());


        //处理已被删除的用户
        if (!CollectionUtils.isEmpty(hasRemovedUserIds)) {
            for (Long userId : hasRemovedUserIds) {
                //更新用户的角色名称
                List<Map<String, Object>> userRoleNames = roleMapper.findRoleNameByUserIdExceptId(userId, sysRole.getRoleId());
                StringBuilder nameBuilder = new StringBuilder();
                for (Map<String, Object> nameMap : userRoleNames) {
                    if (nameBuilder.length() == 0) {
                        nameBuilder.append(nameMap.get("role_name").toString());
                    } else {
                        nameBuilder.append(",").append(nameMap.get("role_name").toString());
                    }
                }
                String roleNames = nameBuilder.toString();
                executeUpdate("update sys_user set own_roles='" + roleNames + "' where user_id=" + userId);


            }
        }
        //删除原有的人员角色关系
        sysActRepository.deleteByRoleId(roleUserDTO.getRoleId());
        //保存新的人员角色关系
        if (!CollectionUtils.isEmpty(roleUserDTO.getUserDepts())) {
            for (UserDeptDTO userDeptDTO : roleUserDTO.getUserDepts()) {
                SysAct sysAct = new SysAct();
                sysAct.setRoleId(roleUserDTO.getRoleId());
                sysAct.setUserId(userDeptDTO.getUserId());
                sysAct.setDeptId(userDeptDTO.getDeptId());
                sysActRepository.save(sysAct);

            }
        }
        //更新用户的拥有角色名称
        if (CollectionUtils.isEmpty(addUserIds)) {
            for (Long userId : addUserIds) {
                //更新用户角色名称
                SysUser user = sysUserRepository.findById(userId).orElse(null);;
                StringBuilder ownRoleName = new StringBuilder();
                if (StringUtils.isNotBlank(user.getOwnRoles())) {
                    ownRoleName.append(user.getUserName()).append(",");
                }
                ownRoleName.append(sysRole.getRoleName());
                executeUpdate("update sys_user set own_roles='" + ownRoleName.toString() + "' where user_id=" + userId);
            }
        }

        StringBuilder userBuilder = new StringBuilder();
        if (!CollectionUtils.isEmpty(newUserIds)) {
            List<SysUser> userList = sysUserRepository.findByUserIdIn(newUserIds);

            //更新角色的用户名称
            for (SysUser user : userList) {
                //角色用户名称拼接
                if (userBuilder.length() == 0) {
                    userBuilder.append(user.getUserName());
                } else {
                    userBuilder.append(",").append(user.getUserName());
                }
            }

            sysRole.setGrantUsers(userBuilder.toString());
        }else{
            sysRole.setGrantUsers(null);
        }
        repository.save(sysRole);
        List<String> adduserNameList = saveAuthlog(projectId, data, ip, addUserIds, sysRole, true);
        List<String> deluserNameList = saveAuthlog(projectId, data, ip, hasRemovedUserIds, sysRole, false);
        Map<String, List<String>> map = Maps.newHashMap();
        map.put("adduser", adduserNameList);
        map.put("deluser", deluserNameList);
        return map;
    }

    @Override
    public void importRole(InputStream is, Long projectId,String userNo) {
        Workbook workbook = null;
        SysRole role=null;
        List<SysRole> roles=new ArrayList<>();
        List<String> roleCodes=new ArrayList<>();
        try {
            workbook = WorkbookFactory.create(is);
            for (int numSheet = 0; numSheet < workbook.getNumberOfSheets(); ++numSheet) {
                Sheet xssfSheet = workbook.getSheetAt(numSheet);
                if (xssfSheet != null) {
                    for (int rowNum = 1; rowNum <= xssfSheet.getLastRowNum(); ++rowNum) {
                        Row xssfRow = xssfSheet.getRow(rowNum);
                        if (xssfRow != null) {
                            role = new SysRole();
                            String roleCode = (String) ExcelUtil.getCellValue(xssfRow.getCell(0));
                            String roleName = (String) ExcelUtil.getCellValue(xssfRow.getCell(1));
                            String status = (String) ExcelUtil.getCellValue(xssfRow.getCell(2));
                            String description = (String) ExcelUtil.getCellValue(xssfRow.getCell(3));
                            if(!StringUtils.isNotEmpty(roleCode)) {
                                throw new ApplicationException("第"+rowNum+"行，角色编码不能为空！");
                            }

                            if (roleCodes.contains(roleCode)) {
                                throw new ApplicationException("第"+rowNum+"行，角色编码不能重复！");
                            }
                            roleCodes.add(roleCode);
                            role.setRoleCode(roleCode);
                            if(!StringUtils.isNotEmpty(roleName)){
                                throw new ApplicationException("第" + rowNum + "行，角色名称不能为空！");
                            }
                            role.setRoleName(roleName);
                            if(!StringUtils.isNotEmpty(status)){
                                //默认开启
                                role.setDataStatus((short)1);
                            }else{
                                role.setDataStatus("启用".equals(status)?(short)1:(short)0);
                            }
                            role.setRemark(description);
                            role.setProjectId(projectId);
                            role.setCreatedTime(new Date());
                            role.setCreator(userNo);
                            role.setJson("{}");
                            role.setVersion(0);
                            roles.add(role);
                        }
                    }
                }
            }

            List<SysRole> roleIds = this.findSysRoleByProjectId(projectId);
            if(!CollectionUtils.isEmpty(roleIds)){
                StringBuffer sb=new StringBuffer();
                for(SysRole sysRole:roleIds){
                    sb.append(sysRole.getRoleId()).append(",");
                }
                String ids="("+sb.replace(sb.length()-1,sb.length(),")").toString();

                //删除sys_act
                String sql="delete from sys_act where role_id in " +ids;
                this.executeUpdate(sql);
                //删除sys_project_acl
                sql="delete from sys_project_acl where role_id in " +ids;
                this.executeUpdate(sql);

                sql="delete from sys_role where project_id="+projectId;
                //删除sys_role
                this.executeUpdate(sql);

            }
            //插入数据
            sysRoleRepository.saveAll(roles);
        } catch (Exception e) {
            throw new ApplicationException(e);
    }
    }


    public List<SysRole> findSysRoleByProjectId(Long projectId){
        String sql="select role_id roleId from sys_role where project_id="+projectId;
        List<SysRole> roleIds = (List<SysRole>) this.selectList(SysRole.class,sql);
        return roleIds;
    }
    /**
     * @param projectId
     * @param data
     * @param ip
     * @param addUserIds
     * @param sysRole
     * @param flag       ture 表示新增的，false表示删除的
     */
    private List<String> saveAuthlog(Long projectId, String data, String ip, List<Long> addUserIds, SysRole sysRole, boolean flag) {
        try {
            int i = 1;
            log.error("aaaaaaaaaaaaaaaaaa:"+(i+1));
            List<String> userNameList = Lists.newArrayList();
            for (Long userId : addUserIds) {
                log.error("userId:"+userId);
                SysUser sysUser = sysUserRepository.findById(userId).orElse(null);
                log.error("111111:");
                SysAuthLog sysAuthLog = new SysAuthLog();
                SysGroup sysGroup = sysGroupRepository.findById(sysUser.getGroupId()).orElse(null);
                log.error("222222:");
                sysAuthLog.setGroupNo(sysGroup.getGroupNo());
                sysAuthLog.setGroupName(sysGroup.getGroupName());
                if (projectId != null) {
                    log.error("3333333:");
                    SysProject sysProject = sysProjectRepository.findById(projectId).orElse(null);
                    log.error("4444444:");
                    sysAuthLog.setProjectId(projectId);
                    sysAuthLog.setProjectName(sysProject.getProjectName());
                }
                if (sysUser.getDeptId() != null) {
                    log.error("555555555:");
                    SysDeptment sysDeptment = sysDeptmentRepository.findById(sysUser.getDeptId()).orElse(null);

                    if (sysDeptment != null) {
//                        String depename = getDeptFullPath(String.valueOf(sysDeptment.getDeptId()));
//                        String grouppath = getGroupFullPath(String.valueOf(sysDeptment.getGroupId()));
//                        sysAuthLog.setUserFullPath(grouppath + "\\" + depename + "\\" + sysUser.getUserName());
                    }
                    //sysAuthLog.setUserFullPath(sysDeptment.getFullPath()+"/"+sysUser.getUserName());
                }
//                sysAuthLog.setUserNo(sysUser.getUserNo());
//                sysAuthLog.setUserName(sysUser.getUserName());
//                sysAuthLog.setLogMsg(flag ? "[授权日志:新增了人员" + sysUser.getUserName() + "]" : "[[授权日志:删除了人员" + sysUser.getUserName() + "]");
//                sysAuthLog.setIp(ip);
//                sysAuthLog.setActionTime(new Date());
//                sysAuthLog.setRoleNo(sysRole.getRoleCode());
//                sysAuthLog.setRoleName(sysRole.getRoleName());
//                sysAuthLog.setBizData(data);
//                sysAuthLogRepository.save(sysAuthLog);
                log.error("66666666:");
                userNameList.add(flag ? "新增" + "名字:" + sysUser.getUserName() + " ,角色:" + sysRole.getRoleName() : "删除" + "名字:" + sysUser.getUserName() + " ,角色:" + sysRole.getRoleName());
                log.error("7777777:");
            }
            log.error("8888888888:");
            return userNameList;
        } catch (Exception e) {
            throw new ApplicationException(e.getMessage());
        }

    }

    /**
     * 获取部门路径
     *
     * @param pid
     * @return
     */
    public String getDeptFullPath(String pid) {
        try {

            SysDeptment sysDeptment = sysDeptmentRepository.findById(Long.valueOf(pid)).get();

            List<String> path = Lists.newArrayList();
            if (sysDeptment.getPid() != null) {
                String deptpathname = getDeptFullPath(String.valueOf(sysDeptment.getPid())) + "\\" + sysDeptment.getDeptName();
                return deptpathname;
            }
            return sysDeptment.getDeptName();
        } catch (Exception e) {

            return e.getMessage();
        }

    }

    /**
     * h获取机构路径
     *
     * @param pid
     * @return
     */
    public String getGroupFullPath(String pid) {
        try {

            SysGroup sysGroup = sysGroupRepository.findById(Long.valueOf(pid)).get();

            List<String> path = Lists.newArrayList();
            if (sysGroup.getPid() != null) {
                String grouppathname = getGroupFullPath(String.valueOf(sysGroup.getPid())) + "\\" + sysGroup.getGroupName();
                return grouppathname;
            }
            return sysGroup.getGroupName();
        } catch (Exception e) {

            return e.getMessage();
        }

    }

}